package amd64

import (
	"fmt"
	"strings"
	"sync"
)

// TextNode是指令接口，代表汇编指令
type TextNode interface {
	//Type返回go类型
	Type() TextTypeEnum
	String() string
	//Asm返回对应汇编指令（能用于fasm汇编器）
	Asm() string
	GetVRegUseInfo() VRegUseInfo
}

type DataNode interface {
	Kind() DataKindEnum
	String() string
	Asm() string
}

type Text struct {
	Texts  [][]TextNode
	Thread bool
}

func NewText(Thread bool) *Text {
	return &Text{
		Thread: Thread,
	}
}

func (text *Text) AddSlice(nodes [][]TextNode) {
	text.Texts = nodes
}

func (text *Text) Silce() {
	nlen := len(text.Texts) - 1
	if nlen == -1 {
		return
	}
	nonilin := 0
	if text.Texts[nlen] != nil {
		return
	}
	for i := nlen; i > 0; i-- {
		if text.Texts[i] != nil {
			nonilin = i
		}
	}
	text.Texts = text.Texts[0 : nonilin+1]
}

func (text *Text) GoString() string {
	var buf strings.Builder
	buf.Grow(10)
	buf.WriteString("&amd64.Text{\n")
	buf.WriteString("Text:")
	for i := 0; i < len(text.Texts); i++ {
		if text.Texts[i] == nil {
			buf.WriteString("<nil>")
			continue
		}
		for j := 0; j < len(text.Texts[i]); j++ {
			buf.WriteString("\n")
			buf.WriteString(text.Texts[i][j].String())
		}
	}
	buf.WriteString("\n")
	buf.WriteString("}")
	return buf.String()
}

func (text *Text) Asm() string {
	var buf strings.Builder
	buf.Grow(10)
	buf.WriteString(_text)
	for i := 0; i < len(text.Texts); i++ {
		if text.Texts[i] == nil {
			continue
		}
		for j := 0; j < len(text.Texts[i]); j++ {
			buf.WriteString("\n")
			buf.WriteString(text.Texts[i][j].Asm())
		}
	}
	buf.WriteString(Exit)
	return buf.String()
}

type Data struct {
	Datas  []DataNode
	lock   sync.Mutex
	Thread bool
}

func NewData(Thread bool) *Data {
	return &Data{
		Datas:  make([]DataNode, 0, 100),
		Thread: Thread,
	}
}

func (data *Data) Add(nodes DataNode) {
	if data.Thread {
		data.lock.Lock()
	}
	data.Datas = append(data.Datas, nodes)
	if data.Thread {
		data.lock.Unlock()
	}
}

func (data *Data) Silce() {
	nlen := len(data.Datas) - 1
	if nlen == -1 {
		return
	}
	nonilin := 0
	if data.Datas[nlen] != nil {
		return
	}
	for i := nlen; i > 0; i-- {
		if data.Datas[i] != nil {
			nonilin = i
		}
	}
	data.Datas = data.Datas[0 : nonilin+1]
}

func (data *Data) GoString() string {
	var buf strings.Builder
	buf.Grow(10)
	buf.WriteString("&amd64.Data{\n")
	buf.WriteString("Data:")
	for i := 0; i < len(data.Datas); i++ {
		if data.Datas[i] == nil {
			buf.WriteString("<nil>")
			continue
		}
		buf.WriteString("\n")
		buf.WriteString(data.Datas[i].String())
	}
	buf.WriteString("\n")
	buf.WriteString("}")
	return buf.String()
}

func (data *Data) Asm() string {
	var buf strings.Builder
	buf.Grow(10)
	buf.WriteString(_data)
	for i := 0; i < len(data.Datas); i++ {
		if data.Datas[i] == nil {
			continue
		}
		buf.WriteString(data.Datas[i].Asm())
	}
	return buf.String()
}

// VRegUseInfo表示一个虚拟寄存器使用信息
type VRegUseInfo struct {
	X86 int16 //x86寄存器使用数量
	SSE int16 //sse寄存器使用数量
}

// NewVRegUseInfo创建一个虚拟寄存器使用信息
func NewVRegUseInfo(X86 int16, SSE int16) VRegUseInfo {
	return VRegUseInfo{X86: X86, SSE: SSE}
}

// IsZero返回是否为零值
func (v VRegUseInfo) IsZero() bool {
	if v.X86 == 0 && v.SSE == 0 {
		return true
	}
	return false
}

// Add 将两个虚拟寄存器使用信息（v , a）相加，并返回和
func (v VRegUseInfo) Add(a VRegUseInfo) VRegUseInfo {
	v.X86 += a.X86
	v.SSE += a.SSE
	return v
}

// add更新虚拟寄存器使用信息
func (v VRegUseInfo) add(reg RegEnum) VRegUseInfo {
	vrm1 := _RegEnumTovrm(reg)
	switch vrm1.Type {
	case vrmx86:
		v.X86++
	case vrmsse:
		v.SSE++
	}
	return v
}

// copy复制虚拟寄存器使用信息
func (v VRegUseInfo) copy() VRegUseInfo {
	return v
}

// string返回虚拟寄存器使用信息（fmt的%+v）字符串
func (v VRegUseInfo) string() string {
	return fmt.Sprintf("%+v\n", v.copy())
}
